use super::AttributeInfo;

// LineNumberTable_attribute {
// u2 attribute_name_index;
// u4 attribute_length;
// u2 line_number_table_length; // 长度
// {   u2 start_pc; // 字节码行号
//     u2 line_number; // 源代码行号
// } line_number_table[line_number_table_length];
// }

// TODO method需要这个，classfile不会改变，暂用clone
// 用于描述Java源码行号与字节码行号（字节码的偏移量）之间的对应关系。
// 主要用于抛出异常时显示显示出错行号、调试程序时按照源码行来设置断点。

// 默认生成，可在javac中通过使用-g：none或-g：lines选项来取消或要求生成这项信息。

// LineNumberTable属性
#[derive(Clone, Default)]
pub struct LineNumberTableAttribute {
    line_number_table: Vec<LineNumberTableEntry>
}

impl AttributeInfo for LineNumberTableAttribute {
    fn read_info(&mut self, reader: &mut crate::classfile::ClassReader) {
        let line_number_table_length = reader.read_u16();
        for _ in 0..line_number_table_length {
            self.line_number_table.push(
                LineNumberTableEntry { 
                    start_pc: reader.read_u16(), 
                    line_number: reader.read_u16()
                }
            )
        }
    }
}

impl LineNumberTableAttribute {
    pub fn new() -> LineNumberTableAttribute {
        LineNumberTableAttribute { line_number_table: vec![] }
    }

    pub fn get_line_number(&self, pc: i32) -> i32 {
        for i in (0..self.line_number_table.len()).rev() {
            let entry = &self.line_number_table[i];
            if pc >= entry.start_pc as i32 {
                return entry.line_number as i32;
            }
        }
        -1
    }
}

// line_number_info表包含start_pc和line_number两个u2类型的数据项，前者是字节码行号，后者是Java源码行号。
#[derive(Clone)]
pub struct LineNumberTableEntry {
    pub start_pc: u16,
    pub line_number: u16
}